﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GestionePolveri2.DAL;
using GestionePolveriLib.BL;
using GestionePolveriLib.Facades.Exceptions;
using FrameworkLib.Facades;
using FrameworkLib.Filters;
using LinqKit;
using System.Data.Objects;

namespace GestionePolveriLib.Facades
{
    [Serializable]
    public class PolvereFacade : FacadeBase<GestionePolveriEntities>
    {
        GestionePolveriEntities context = null;

        public PolvereFacade()
        {
            context = this.GetContext();
        }

        public PolvereFacade(string connectionString)
        {
            context = this.GetContext(connectionString);
        }

        public void LoadAsync(BackgroundWorkerCallbackBase.Callback callback)
        {
            this.RunAsync(() => GetAll(), callback);
        }

        public List<Polvere> GetAll()
        {
            List<Polvere> retValue = null;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri
                          select new Polvere
                          {
                              ID = x.IDPolvere,
                              CodicePolvere = x.CodicePolvere,
                              Descrizione = x.Descrizione,
                              Note = x.Note,
                              ScortaMinima = x.ScortaMinima,
                              IsCodiceCustom = x.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == x.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault(),
                              TipologiaSM = new TipologiaScortaMinima() { 
                                  ID = x.TipologieScortaMinimaPolvere.IDTipologiaScortaMinimaPolvere, 
                                  Codice=x.TipologieScortaMinimaPolvere.Codice, 
                                  Descrizione = x.TipologieScortaMinimaPolvere.Descrizione
                              }
                          };

                if (obj.Any())
                {
                    retValue = obj.ToList();

                    //
                    LoadInformazioniAccessorie(retValue);

                    //ComposizioneColoreFacadeExt ccf = new ComposizioneColoreFacadeExt();

                    //retValue = obj.ToList();

                    //foreach (Polvere p in retValue)
                    //{
                    //    p.ColoriAbbinati = ccf.GetColoriAssociati2(p.ID);
                    //    p.FamiglieColori = ccf.GetFamiglieColoriAssociate(p.ID);
                    //}
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }

        private void LoadInformazioniAccessorie(List<Polvere> retValue)
        {
            List<LookUp_FamiglieColori_ColoriAbbinati_Result> mmm = (List<LookUp_FamiglieColori_ColoriAbbinati_Result>)FrameworkLib.Utilities.Singleton<GestionePolveriLib.Cache.LookUpData>.Instance.GetData("LookupFamiglie");
            foreach (Polvere p in retValue)
            {
                LookUp_FamiglieColori_ColoriAbbinati_Result r = mmm.Find(x => x.IDPolvere == p.ID);

                if (r != null)
                {
                    p.FamiglieColori = r.Famiglia;
                    p.ColoriAbbinati = r.ColoriAbbinati;
                    p.Applicazione = r.Applicazione;
                }
            }
        }

        private void LoadInformazioniAccessorie(Polvere retValue)
        {
            List<LookUp_FamiglieColori_ColoriAbbinati_Result> mmm = (List<LookUp_FamiglieColori_ColoriAbbinati_Result>)FrameworkLib.Utilities.Singleton<GestionePolveriLib.Cache.LookUpData>.Instance.GetData("LookupFamiglie");
         
            LookUp_FamiglieColori_ColoriAbbinati_Result r = mmm.Find(x => x.IDPolvere == retValue.ID);

            if (r != null)
            {
                retValue.FamiglieColori = r.Famiglia;
                retValue.ColoriAbbinati = r.ColoriAbbinati;
                retValue.Applicazione = r.Applicazione;
            }
        }

        public List<Polvere> GetAll(FilterBase<AnagPolveri> filter)
        {
            List<Polvere> retValue = null;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri.AsExpandable().Where(filter.SetUpFilter())
                          select new Polvere
                          {
                              ID = x.IDPolvere,
                              CodicePolvere = x.CodicePolvere,
                              Descrizione = x.Descrizione,
                              Note = x.Note,
                              ScortaMinima = x.ScortaMinima,
                              IsCodiceCustom = x.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == x.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault(),
                              TipologiaSM = new TipologiaScortaMinima() {
                                  ID = x.TipologieScortaMinimaPolvere.IDTipologiaScortaMinimaPolvere,
                                  Codice = x.TipologieScortaMinimaPolvere.Codice,
                                  Descrizione = x.TipologieScortaMinimaPolvere.Descrizione
                              }
                          };

                if (obj.Any())
                {
                    retValue = obj.ToList();
                    LoadInformazioniAccessorie(retValue);
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }

        public List<PolvereExt> GetAllEssential()
        {
            List<PolvereExt> retValue = null;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri
                          select new PolvereExt
                          {
                              Note = x.Note,
                              Base = false,
                              Venatura = false,
                              ID = x.IDPolvere,
                              CodicePolvere = x.CodicePolvere,
                              Descrizione = x.Descrizione,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == x.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault()
                          };

                var ts = ((ObjectQuery)obj).ToTraceString();
                if (obj.Any())
                {
                    retValue = obj.ToList();
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }

        public bool Add(Polvere data)
        {
            bool retValue = false;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                if (!context.AnagPolveri.Any(x => x.CodicePolvere == data.CodicePolvere))
                {
                    AnagPolveri imp = new AnagPolveri();
                    imp.CodicePolvere = data.CodicePolvere;
                    imp.Descrizione = data.Descrizione;
                    imp.Note = data.Note;
                    imp.IDFornitore = data.Fornitore.ID;
                    imp.ScortaMinima = data.ScortaMinima;
                    imp.IsCodiceCustom = data.IsCodiceCustom;
                    imp.IDTipologiaScortaMinimaPolvere = (short)data.TipologiaSM.ID;

                    context.AnagPolveri.AddObject(imp);
                    context.SaveChanges();

                    data.ID = imp.IDPolvere;
                }
                else
                {
                    AnagPolveri imp = context.AnagPolveri.FirstOrDefault(x => x.CodicePolvere == data.CodicePolvere);
                    if (imp != null)
                    {
                        data.ID = imp.IDPolvere;
                        data.CodicePolvere = imp.CodicePolvere;
                        data.Descrizione = imp.Descrizione;
                        data.Note = imp.Note;
                        data.Fornitore.ID = imp.IDFornitore;
                        data.ScortaMinima = imp.ScortaMinima;
                        data.IsCodiceCustom = imp.IsCodiceCustom;
                        data.TipologiaSM.ID = imp.IDTipologiaScortaMinimaPolvere;
                    }

                    //throw new DuplicatedRecordException("Codice Polvere Duplicato !");
                }

                retValue = true;
            }
            catch (Exception ex)
            {
                throw;
            }
            
            return retValue;
        }

        public bool Delete(Polvere data)
        {
            bool retValue = false;

            try
            {
                var obj = from x in context.AnagPolveri
                          where x.IDPolvere == data.ID
                          select x;

                if (obj.Any())
                {
                    FamiglieColoriXPolveriFacade fcxpf = new FamiglieColoriXPolveriFacade();
                    BL.FamiglieColoriXPolveri m_famColXPolv = fcxpf.Get(data.ID);
                    fcxpf.Delete(m_famColXPolv);

                    this.GetContext().AnagPolveri.DeleteObject(obj.FirstOrDefault());
                    this.GetContext().SaveChanges();

                    retValue = true;
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return retValue;
        }

        public bool Modify(Polvere data)
        {
            bool retValue = false;

            try
            {
                var obj = from x in context.AnagPolveri
                          where x.IDPolvere == data.ID
                          select x;

                if (obj.Any())
                {
                    AnagPolveri imp = obj.FirstOrDefault();
                    imp.CodicePolvere = data.CodicePolvere;
                    imp.Descrizione = data.Descrizione;
                    imp.Note = data.Note;
                    imp.IDFornitore = data.Fornitore.ID;
                    imp.ScortaMinima = data.ScortaMinima;
                    imp.IsCodiceCustom = data.IsCodiceCustom;
                    imp.IDTipologiaScortaMinimaPolvere = (short)data.TipologiaSM.ID;

                    this.GetContext().SaveChanges();

                    retValue = true;
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }

      

        public Polvere Get(int id)
        {
            Polvere retValue = null;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri
                          where x.IDPolvere == id
                          select new Polvere
                          {
                              ID = x.IDPolvere,
                              CodicePolvere = x.CodicePolvere,
                              Descrizione = x.Descrizione,
                              Note = x.Note,
                              ScortaMinima = x.ScortaMinima,
                              IsCodiceCustom = x.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == x.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault()
                          };

                if (obj.Any())
                {
                    retValue = obj.FirstOrDefault();

                    LoadInformazioniAccessorie(retValue);
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }

        public List<Polvere> GetbyLotto(long idLotto)
        {
            List<Polvere> retValue = null;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.Lotti
                          join p in context.AnagPolveri on x.IDPolvere equals p.IDPolvere
                          where x.IDLotto == idLotto
                          select new Polvere
                          {
                              ID = p.IDPolvere,
                              CodicePolvere = p.CodicePolvere,
                              Descrizione = p.Descrizione,
                              Note = p.Note,
                              ScortaMinima = p.ScortaMinima,
                              IsCodiceCustom = p.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == p.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault()
                          };

                if (obj.Any())
                {
                    retValue = obj.ToList();
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }

        public string GetColoriAssociati(string codicePolvere)
        {
            string retValue = null;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = (from x in context.ComposizioneColori
                           where x.AnagPolveri.CodicePolvere == codicePolvere
                           select (x.AnagColori.CodiceColore + ", ")).Distinct();

                if (obj.Any())
                {
                    obj.ToList().ForEach(x => retValue += x);

                    int i = retValue.LastIndexOf(",");

                    retValue = retValue.Substring(0, i);
                }

            }
            catch (Exception ex)
            {
            }

            return retValue;
        }

        public string GetFamiglieAssociati(string codicePolvere)
        {
            string retValue = null;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = (from x in context.ComposizioneColori
                           where x.AnagPolveri.CodicePolvere == codicePolvere
                           select (x.AnagColori.AnagFamiglie.Descrizione + ", ")).Distinct();

                if (obj.Any())
                {
                    obj.ToList().ForEach(x => retValue += x);

                    int i = retValue.LastIndexOf(",");

                    retValue = retValue.Substring(0, i);
                }

            }
            catch (Exception ex)
            {
            }

            return retValue;
        }

        public bool HasPolveriByFornitore(int idFornitore)
        {
            bool retValue = false;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri
                          where x.IDFornitore == idFornitore
                          select x;

                if (obj.Any())
                {
                    retValue = true;
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }


        public List<Polvere> GetScortaMinimaInfo()
        {
            //metodo non utilizzato - non aggiunto ll.tipo==1
            List<Polvere> retValue = null;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri 
                          join ll in context.Lotti on x.IDPolvere equals ll.IDPolvere
                          group x by new { x.CodicePolvere, x.Descrizione, x.Note, x.ScortaMinima, x.IsCodiceCustom, x.IDFornitore, x.IDPolvere } into grp
                          orderby grp.Key.CodicePolvere
                          select new Polvere
                          {
                              ID = grp.Key.IDPolvere,
                              CodicePolvere = grp.Key.CodicePolvere,
                              Descrizione = grp.Key.Descrizione,
                              Note = grp.Key.Note,
                              ScortaMinima = grp.Key.ScortaMinima,
                              Giacenza = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere select l.Giacenza).Sum(),
                              IsCodiceCustom = grp.Key.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == grp.Key.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault()
                          };

                if (obj.Any())
                {
                    retValue = obj.ToList();
                    LoadInformazioniAccessorie(retValue);

                    //ComposizioneColoreFacadeExt ccf = new ComposizioneColoreFacadeExt();

                    //foreach (Polvere p in retValue)
                    //{
                    //    p.ColoriAbbinati = ccf.GetColoriAssociati2(p.ID);
                    //    p.FamiglieColori = ccf.GetFamiglieColoriAssociate(p.ID);
                    //}
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }

        public List<Polvere> GetScortaMinimaInfo(FilterBase<AnagPolveri> filter)
        {
            //metodo non utilizzato - non aggiunto ll.tipo==1

            List<Polvere> retValue = null;

            try
            {
                //GestionePolveriEntities context = this.GetContext();
                var obj = from x in context.AnagPolveri.AsExpandable().Where(filter.SetUpFilter())
                          join ll in context.Lotti on x.IDPolvere equals ll.IDPolvere
                          group x by new { x.CodicePolvere, x.Descrizione, x.Note, x.ScortaMinima, x.IsCodiceCustom, x.IDFornitore, x.IDPolvere } into grp
                          orderby grp.Key.CodicePolvere
                          select new Polvere
                          {
                              ID = grp.Key.IDPolvere,
                              CodicePolvere = grp.Key.CodicePolvere,
                              Descrizione = grp.Key.Descrizione,
                              Note = grp.Key.Note,
                              ScortaMinima = grp.Key.ScortaMinima,
                              Giacenza = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere select l.Giacenza).Sum(),
                              IsCodiceCustom = grp.Key.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == grp.Key.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault()
                          };

                if (obj.Any())
                {
                    retValue = obj.ToList();
                    LoadInformazioniAccessorie(retValue);

                    //ComposizioneColoreFacadeExt ccf = new ComposizioneColoreFacadeExt();

                    //retValue = obj.ToList();

                    //foreach (Polvere p in retValue)
                    //{
                    //    p.ColoriAbbinati = ccf.GetColoriAssociati2(p.ID);
                    //    p.FamiglieColori = ccf.GetFamiglieColoriAssociate(p.ID);
                    //}
                }
            }
            catch (Exception ex)
            {
                // throw ex;
            }

            return retValue;
        }

        public Polvere GetScortaMinimaInfo(int idPolvere)
        {
            Polvere retValue = null;

            try
            {
                var obj = from x in context.AnagPolveri
                          join ll in context.Lotti on x.IDPolvere equals ll.IDPolvere
                          where x.IDPolvere == idPolvere
                          group x by new { x.CodicePolvere, x.Descrizione, x.Note, x.ScortaMinima, x.IsCodiceCustom, x.IDFornitore, x.IDPolvere } into grp
                          orderby grp.Key.CodicePolvere
                          select new Polvere
                          {
                              ID = grp.Key.IDPolvere,
                              CodicePolvere = grp.Key.CodicePolvere,
                              Descrizione = grp.Key.Descrizione,
                              Note = grp.Key.Note,
                              ScortaMinima = grp.Key.ScortaMinima,
                              Giacenza = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere select l.Giacenza).Sum(),
                              QuantitaImpegnata = (from pr in context.Prenotazioni where pr.IDPolvere == grp.Key.IDPolvere && !pr.IsAnnullata select pr.Quantita).Sum(),
                              QuantitaNC = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere && l.LottiNC.FlagNC select l.Giacenza).Sum(),
                              QuantitaNCBlocked = (from l in context.Lotti where l.IDPolvere == grp.Key.IDPolvere && l.LottiNC.FlagBlocco select l.Giacenza).Sum(),
                              IsCodiceCustom = grp.Key.IsCodiceCustom,
                              Fornitore = (from y in context.AnagFornitori
                                           where y.IDFornitore == grp.Key.IDFornitore
                                           select new Fornitore
                                           {
                                               ID = y.IDFornitore,
                                               Descrizione = y.Descrizione,
                                               Note = y.Note
                                           }).FirstOrDefault()
                          };

                if (obj.Any())
                {
                    retValue = obj.FirstOrDefault();
                    LoadInformazioniAccessorie(retValue);
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return retValue;
        }
    }
}
